package com.udp.nml;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.math.BigDecimal;
import java.net.SocketAddress;
import java.util.Date;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.nml.sensors.SensorEntityManager;
import com.nml.sensors.Transmission;

/**
 * Example UDP Handler Adapter showing how to read individual bytes from a UDP message.
 * 
 * @author Niall McLoughlin
 */
public class UDPHandler extends IoHandlerAdapter 
{
	static Logger logger = LoggerFactory.getLogger(UDPHandler.class);
	
	private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
	
	private String logText = new String();
	
	public String getLogText() 
	{
		return logText;
	}

	public void setLogText(String logText) 
	{
		String oldValue = this.logText;
		
		if (logText.length() > 5000)
		{
			logText = logText.substring((logText.length() - 5000));
		}
		this.logText = logText;
		pcs.firePropertyChange("logText", oldValue, logText);
	}

	public UDPHandler()
	{
		
	}
	
	public UDPHandler(PropertyChangeListener propertyChangeListener)
	{
		pcs.addPropertyChangeListener("logText", propertyChangeListener);
	}
	
	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception 
	{		
        logger.info(">>> messageReceived");
        
		if (message instanceof IoBuffer) 
        {
            // Cast the message to an IoBuffer. 
			// The basic DatagramSocket messages arrive as an IoBuffer and the 
			// Apache Mina version does too.
			IoBuffer buffer = (IoBuffer) message;
			
			// Get the address of the remote client.
            SocketAddress remoteAddress = session.getRemoteAddress();
            
            // Get the message as a long primitive. long primitives are 8 bytes.
            long sentMessage = buffer.getLong();
            
            // Get the message as a byte array. 
            // Individual byte values can be read from the array or the 
            // full byte array can be used to create an object such as a String.
            byte[] array = buffer.array();
            
            // Read byte position 6.
            byte name = array[6];
            
            // Create a String from the byte array.  
            // We're assuming the original bytes we're pulled from a String by the client before the message was sent.
            String stringName = new String(array);
            
            String logMessage = 
            	"Remote Address:" + remoteAddress + "\n Message as String: " +
            	stringName + "\n Message As long (8 byte primitive) type: " + sentMessage + "\nbtye from Array Index 7: " + array[7];
            
            // Log the message.
            logger.info(logMessage);
        
            String logLocal = logText + "\n" + logMessage; 
            setLogText(logLocal);
            
            sendAcknowledgement(session);
            
            Transmission transmission = new Transmission();
            transmission.setRawBytes(stringName);

            SensorEntityManager.saveTransmission(transmission);
        } 
		
		logger.info("<<< messageReceived");
	}
	
	private void sendAcknowledgement(IoSession session)
	{
		logger.info(">>> sendAcknowledgement");
		
		String response = "Thanks, Got your message ok.";  
        byte[] responseAsBytes = response.getBytes();
        
        IoBuffer buffer = IoBuffer.allocate(responseAsBytes.length);
        buffer.put(responseAsBytes);
        buffer.flip();
        
        session.write(buffer);
        
        logger.info("<<< sendAcknowledgement");
	}
	
	@Override
	public void sessionCreated(IoSession session) throws Exception 
	{
		logger.info(">>> sessionCreated");
		
		super.sessionCreated(session);
		
		logger.info("<<< sessionCreated");
	}
	
	@Override
	public void sessionClosed(IoSession session) throws Exception 
	{
		logger.info(">>> sessionClosed");
		
		super.sessionClosed(session);
		
		logger.info("<<< sessionClosed");
	}
	
	@Override
	public void messageSent(IoSession session, Object message) throws Exception 
	{
		logger.info(">>> messageSent");
		
		super.messageSent(session, message);
		
		logger.info("<<< messageSent");
	}
}